#include "led.h"
#include "system_stm32f4xx.h"
#include "iwdg.h"
#include "at24cxx.h"
#include "sys.h"
#include "w25qxx.h"
#include "sdram.h"
#include "my_malloc.h"
#include "usart.h"
#include "ftl.h"

#include "rtthread.h"
#include <string.h>
#include <stdio.h>
#include "delay.h"

/* 定义线程控制块 */
static rt_thread_t uart_thread = RT_NULL;
static void uart_thread_entry(void* parameter) {
    (void)parameter;
    for(;;) {
        if(g_usart_rx_sta) {
            /* 串口接收数据开始 */
            printf("%s\n",g_usart_rx_buf);

            /* 串口接收数据结束 */
            memset(g_usart_rx_buf,0,(g_usart_rx_sta+1));
            g_usart_rx_sta = 0;
        }
        rt_thread_mdelay(200);
    }
}

static rt_thread_t sys_thread = RT_NULL;
static void sys_thread_entry(void* parameter) {
    (void)parameter;
    for(;;) {
        IWDG_FEED; // 喂狗
        if(enterSleep) { // 如果需要进入Standby
            enterSleep = false; // 去除进入标志
            AT24CXX_WriteOneByte(0x05, 0xAA); // 写入进入stanby标志
            /* 备份数据开始 */
            ;
            /* 备份数据结束 */
            softReset(); // 软件复位
        }
        // 统计内存使用率
        memUsed[0] = my_mem_perused(SRAMIN);
        memUsed[1] = my_mem_perused(SRAMEX);
        memUsed[2] = my_mem_perused(SRAMCCM);
        rt_thread_mdelay(10000);
    }
}

int main(void) {
    uint8_t tmpByte = 0;
    SystemCoreClockUpdate(); // 更新SystemCoreClock
    AT24CXX_Init(); // 初始化EEPROM
    if(AT24CXX_Check()) { // 检查I2C是否连通
        errorCode |= 1;
    } else {
        if(AT24CXX_ReadOneByte(0x00) == 0xAA) { // 判断进入standby
            AT24CXX_WriteOneByte(0x00, 0xFF); // 恢复默认值
            /* 关闭外设开始 */
            ; 
            /* 关闭外设结束 */
            wkupInit(); // 开启wakeup按键
            enterStandbyMode(); // 进入standby
        }
    }
    /* 恢复数据备份开始 */

    /* 恢复数据备份结束 */
    ledInit(); // 初始化LED
    norflash_init(); // 初始化W25Q256
    // 检查型号是否正确
    if(g_norflash_type != W25Q256) {
        errorCode |= (1<<1);
        // 读写代码已测试
        // 考虑到flash读写次数限制 不在每次上电后进行读写测试
    }
    sdram_init(); // 初始化SDRAM
    tmpByte = 0x55;
    fmc_sdram_write_buffer(&tmpByte, 0, 1);
    tmpByte = 0;
    fmc_sdram_read_buffer(&tmpByte, 0, 1);
    // 测试SDRAM
    if (tmpByte != 0x55) {
        // SDRAM错误
        errorCode |= (1<<2);
    }
    // 串口1初始化
    usart_init(84, 115200); // 核心频率MHz 波特率
    // MALLOC初始化
    my_mem_init(SRAMIN); /* 初始化内部内存池 */
    my_mem_init(SRAMEX); /* 初始化外部内存池 */
    my_mem_init(SRAMCCM); /* 初始化CCM内存池 */
    // ftl初始化
    if(ftl_init()) { // 这部分耗时较长
        // nand flt错误
        errorCode |= (1<<3);
    }
    // 统计内存使用率
    memUsed[0] = my_mem_perused(SRAMIN);
    memUsed[1] = my_mem_perused(SRAMEX);
    memUsed[2] = my_mem_perused(SRAMCCM);
    // SystemCoreClock 168MHz 0xF42400
    SysTick_Config(SystemCoreClock/RT_TICK_PER_SECOND); // 设置SysTick中断时间间隔1ms

    iwdgInit(0x06, 3750); // 开启独立看门狗 30秒超时

    uart_thread = /* 线程控制块指针 */
    rt_thread_create( "uart_thread", /* 线程名字 */
                      uart_thread_entry, /* 线程入口函数 */
                      RT_NULL, /* 线程入口函数参数 */
                      256, /* 线程栈大小
                            * 某个线程分配的资源过少,会导致整体出现问题
                            * 建议直接给4的倍数,最小64) 
                            */
                      5, /* 线程的优先级 */
                      20); /* 线程时间片 */
    /* 启动线程，开启调度 */
    if (uart_thread != RT_NULL)
        rt_thread_startup(uart_thread);

    sys_thread = /* 线程控制块指针 */
    rt_thread_create( "sys_thread", /* 线程名字 */
                      sys_thread_entry, /* 线程入口函数 */
                      RT_NULL, /* 线程入口函数参数 */
                      256, /* 线程栈大小 */
                      5, /* 线程的优先级 */
                      20); /* 线程时间片 */
    /* 启动线程，开启调度 */
    if (sys_thread != RT_NULL)
        rt_thread_startup(sys_thread);

    for(;;) {
        togglePin(GPIOB, 1); // 翻转一次LED引脚
        rt_thread_mdelay(1000);
    }
    return 0;
}
